package client

import (
	"errors"
	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"lancer/conf"
	"lancer/enum"
	"log"
	"os"
	"time"
)

var (
	GSshClient       *ssh.Client
	GSftpClient      *sftp.Client
	GSshClientHandle Client
)

type Client struct {
}

func (cli *Client) Connect() (sshClient *ssh.Client, sftpClient *sftp.Client, err error) {
	var (
		config *ssh.ClientConfig
		addr   string
	)

	config = &ssh.ClientConfig{
		User:            conf.GConfg.User,           //用户名
		Timeout:         time.Second * enum.Timeout, //超时时间
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Auth:            []ssh.AuthMethod{ssh.Password(conf.GConfg.Password)},
	}

	addr = conf.GConfg.Ip + ":" + conf.GConfg.Port

	if sshClient, err = ssh.Dial("tcp", addr, config); err != nil {
		log.Println("创建ssh client 失败", err)
		return nil, nil, err
	}

	if sftpClient, err = sftp.NewClient(sshClient); err != nil {
		log.Println("创建sftp client 失败", err)
		return nil, nil, err
	}

	return sshClient, sftpClient, err
}

func InitSsh() (err error) {

	GSshClientHandle = Client{}
	GSshClient, GSftpClient, err = GSshClientHandle.Connect()
	return
}

// 执行命令

func (cli *Client) Run(cmd string) (output string, err error) {
	var (
		session        *ssh.Session
		combinedOutput []byte
	)

	if GSshClient == nil {
		err = errors.New("未启动ssh连接")
		return "", err
	}

	if session, err = GSshClient.NewSession(); err != nil {
		return "", err
	}

	defer session.Close()

	combinedOutput, err = session.CombinedOutput(cmd)
	return string(combinedOutput), err
}

//异步非阻塞

func (cli *Client) RunAsync(cmd string, duration time.Duration) (output string, err error) {

	go cli.Run(cmd)

	log.Println("休眠")
	time.Sleep(duration)

	return "", nil
}

// 下载文件

func (cli *Client) DownLoadFile(remoteFile, localFile string) (n int64, err error) {
	var (
		source *sftp.File
		target *os.File
	)

	if GSftpClient == nil {
		err = errors.New("未启动sftp连接")
		return 0, err
	}

	if source, err = GSftpClient.Open(remoteFile); err != nil {
		return 0, err
	}

	defer source.Close()

	if target, err = os.OpenFile(localFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
		return 0, err
	}

	defer target.Close()

	if n, err = io.Copy(target, source); err != nil {
		return 0, err
	}
	return n, nil
}

//上传文件

func (cli *Client) UploadFile(localFile, remoteFileName string) (n int, err error) {
	var (
		file     *os.File
		ftpFile  *sftp.File
		fileByte []byte
	)

	if GSftpClient == nil {
		err = errors.New("未启动sftp连接")
		return 0, err
	}

	if file, err = os.Open(localFile); err != nil {
		return 0, err
	}
	defer file.Close()

	if ftpFile, err = GSftpClient.Create(remoteFileName); err != nil {
		return 0, err
	}

	defer ftpFile.Close()

	if fileByte, err = ioutil.ReadAll(file); err != nil {
		return 0, err
	}

	n, err = ftpFile.Write(fileByte)

	return n, err
}
